﻿// This software is the confidential and proprietary information of NetBay.
// Such confidential information should not be disclosed.
// NetBay copyright(c) 2012

#region

using System;
using System.Collections.Generic;
using System.Configuration;
using NetBay.Core.BusinessEntities.Workflow;
using NetBay.Core.Encryption.Licensing;
using Rio.Applications.Web.Code;
using Rio.Applications.Web.RioWCFWorkflow;
using Rio.Flow.Business.Repository;

#endregion

namespace Rio.Applications.Web
{
    public static class WorkflowController
    {
        #region Readonly & Static Fields

        private static bool _isInit;
        private static string _workflowBindingName = "BasicHttpBinding_IWCFWorkflow";

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes the <see cref="WorkflowController"/> class.
        /// </summary>
        static WorkflowController()
        {
            LoadConfiguration();
        }

        #endregion

        #region Class Properties

        /// <summary>
        /// Indicating whether the workflow functionnality is active in web.config file.
        /// </summary>
        /// <value>
        /// The is workflow active.
        /// </value>
        public static bool IsWorkflowActive
        {
            get
            {
                if (LicenseManager.LicenseTerms != null &&
                    LicenseManager.LicenseTerms.LicenseType == LicenseType.Enterprise)
                {
                    return true;
                }
                return false;
            }
        }

        /// <summary>
        /// Gets the workflow is TCP hosting.
        /// </summary>
        /// <value>
        /// The workflow is TCP hosting.
        /// </value>
        public static string WorkflowBindingName
        {
            get { return _workflowBindingName; }
        }

        #endregion

        #region Class Methods

        /// <summary>
        /// Executes the action.
        /// </summary>
        /// <param name="wkfInstanceId">The WKF instance id.</param>
        /// <param name="wkfActionId">The WKF action id.</param>
        /// <param name="wkfDocumentStateId">The WKF document state id.</param>
        /// <param name="userId">The user id.</param>
        /// <param name="rguid">The rguid.</param>
        /// <param name="uiActionType">Type of the UI action.</param>
        /// <param name="organizationIdentifier">The organization identifier.</param>
        /// <param name="folderTypeIdentifier">The folder type identifier.</param>
        /// <param name="folderIdentifier">The folder identifier.</param>
        /// <param name="parameters">The parameters.</param>
        /// <param name="isGlobalAction">if set to <c>true</c> [is global action].</param>
        /// <returns></returns>
        public static ActionResult ExecuteAction(long wkfInstanceId,
                                                 long wkfActionId,
                                                 List<long> wkfDocumentStateId,
                                                 long userId,
                                                 long rguid,
                                                 WorkflowTypeAction uiActionType,
                                                 long organizationIdentifier,
                                                 long folderTypeIdentifier,
                                                 long folderIdentifier,
                                                 List<Parameter> parameters = null,
                                                 bool isGlobalAction = false)

        {
            if (IsWorkflowActive)
            {
                using (WCFWorkflowClient client = GetRioWCFWorkflowClient())
                {
                    return client.ExecuteAction(wkfInstanceId, wkfActionId, wkfDocumentStateId, userId, rguid,
                                                parameters, isGlobalAction, uiActionType, folderIdentifier,
                                                folderTypeIdentifier, organizationIdentifier);
                }
            }
            return ActionResult.Executed;
        }

        /// <summary>
        /// Gets the rio WCF workflow client.
        /// </summary>
        /// <returns></returns>
        public static WCFWorkflowClient GetRioWCFWorkflowClient()
        {
            return new WCFWorkflowClient(WorkflowBindingName);
        }

        /// <summary>
        /// Starts a workflow.
        /// </summary>
        /// <param name="FolderTypeIdentifier">The folder type identifier.</param>
        /// <param name="FolderIdentifier">The folder identifier.</param>
        /// <param name="startingCondition">The starting condition.</param>
        /// <param name="UserId">The user id.</param>
        /// <param name="DocumentsIdentifier">The documents identifier.</param>
        /// <param name="ChronoId">The chrono id.</param>
        /// <param name="IndexValues">The index values.</param>
        public static bool StartWorkflowDispatcher(long FolderTypeIdentifier, long FolderIdentifier,
                                                   wkfConditionType startingCondition, long UserId,
                                                   List<long> DocumentsIdentifier = null, long ChronoId = 0,
                                                   Dictionary<long, string> IndexValues = null)
        {
            return StartWorkflow(FolderTypeIdentifier, FolderIdentifier, startingCondition, UserId, DocumentsIdentifier,
                          ChronoId, IndexValues);
        }

        /// <summary>
        /// Workflow Opened
        /// </summary>
        /// <param name="wkfDefinitionId">The WKF definition id.</param>
        public static void WorkflowOpened(long wkfDefinitionId)
        {
            if (IsWorkflowActive)
            {
                using (WCFWorkflowClient client = GetRioWCFWorkflowClient())
                {
                    client.WorkflowOpened(wkfDefinitionId);
                }
            }
        }

        /// <summary>
        /// Determines whether this instance [can execute workflow] the specified context.
        /// </summary>
        /// <param name="folderTypeId">The folder type id.</param>
        /// <param name="startingCondition">The starting condition.</param>
        /// <returns>
        ///   <c>true</c> if this instance [can execute workflow] the specified context; otherwise, <c>false</c>.
        /// </returns>
        private static bool CanExecuteWorkflow(long folderTypeId, long startingCondition)
        {
            if (IsWorkflowActive)
            {
                //check if a workflow definition is attached to the context
                return WorkflowDefinitionRepository.HasDefinitionsToStart(folderTypeId, startingCondition);
            }
            return false;
        }

        /// <summary>
        /// Gets the creation context.
        /// </summary>
        /// <param name="FolderTypeIdentifier">The folder type identifier.</param>
        /// <param name="FolderIdentifier">The folder identifier.</param>
        /// <param name="DocumentsIdentifier">The documents identifier.</param>
        /// <param name="startingCondition">The starting condition.</param>
        /// <param name="UserId">The user id.</param>
        /// <param name="ChronoId">The chrono id.</param>
        /// <param name="IndexValues">The index values.</param>
        /// <returns></returns>
        private static CreationContext GetCreationContext(long FolderTypeIdentifier, long FolderIdentifier,
                                                          List<long> DocumentsIdentifier, long startingCondition,
                                                          long UserId, long ChronoId = 0,
                                                          Dictionary<long, string> IndexValues = null)
        {
            CreationContext context = new CreationContext
                                          {
                                              FolderTypeIdentifier = FolderTypeIdentifier,
                                              FolderIdentifier = FolderIdentifier,
                                              DocumentsIdentifier = DocumentsIdentifier,
                                              StartingCondition = startingCondition,
                                              UserId = UserId,
                                              ChronoId = ChronoId,
                                              IndexValues = IndexValues
                                          };
            return context;
        }

        /// <summary>
        /// Inits the configuration.
        /// </summary>
        private static void LoadConfiguration()
        {
            if (!_isInit)
            {
                /*
                 * WorkflowBindingName
                 */

                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["WorkflowBindingName"]))
                {
                    _workflowBindingName = ConfigurationManager.AppSettings["WorkflowBindingName"].ToString();
                }

                _isInit = true;
            }
        }

        /// <summary>
        /// Starts a workflow.
        /// </summary>
        /// <param name="FolderTypeIdentifier">The folder type identifier.</param>
        /// <param name="FolderIdentifier">The folder identifier.</param>
        /// <param name="startingCondition">The starting condition.</param>
        /// <param name="UserId">The user id.</param>
        /// <param name="DocumentsIdentifier">The documents identifier.</param>
        /// <param name="ChronoId">The chrono id.</param>
        /// <param name="IndexValues">The index values.</param>
        private static bool StartWorkflow(long FolderTypeIdentifier,
                                          long FolderIdentifier,
                                          wkfConditionType startingCondition,
                                          long UserId,
                                          List<long> DocumentsIdentifier = null,
                                          long ChronoId = 0,
                                          Dictionary<long, string> IndexValues = null)
        {
            if (IsWorkflowActive)
            {
                if (CanExecuteWorkflow(FolderTypeIdentifier, Convert.ToInt64(startingCondition)))
                {
                    using (WCFWorkflowClient client = GetRioWCFWorkflowClient())
                    {
                        CreationContext context = GetCreationContext(FolderTypeIdentifier, FolderIdentifier,
                                                                     DocumentsIdentifier,
                                                                     Convert.ToInt64(startingCondition), UserId,
                                                                     ChronoId, IndexValues);


                        return client.StartWorkflow(context);
                    }
                }
            }

            return true;
        }

        #endregion
    }
}